package com.usian.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.usian.common.constants.WemediaContans;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.base.BaseServiceImpl;
import com.usian.model.common.dtos.PageResponseResult;
import com.usian.model.common.dtos.ResponseResult;
import com.usian.model.common.enums.AppHttpCodeEnum;
import com.usian.model.media.dtos.WmNewsDto;
import com.usian.model.media.dtos.WmNewsPageReqDto;
import com.usian.model.media.pojos.WmMaterial;
import com.usian.model.media.pojos.WmNews;
import com.usian.model.media.pojos.WmNewsMaterial;
import com.usian.model.media.pojos.WmUser;
import com.usian.model.wemedia.vo.WmNewsVo;
import com.usian.utils.threadlocal.ThreadLocalUtils;
import com.usian.wemedia.mapper.WmMaterialMapper;
import com.usian.wemedia.mapper.WmNewsMapper;
import com.usian.wemedia.mapper.WmNewsMaterialMapper;
import com.usian.wemedia.mapper.WmUserMapper;
import com.usian.wemedia.service.WmNewsService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

import static com.usian.common.constants.message.NewsAutoScanConstants.WM_NEWS_AUTO_SCAN_TOPIC;
import static com.usian.common.constants.message.NewsAutoScanConstants.WM_NEWS_UP_OR_DOWN_TOPIC;

@Service
public class WmNewsServiceImpl extends BaseServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Value("${fdfs.url}")
    private String baseUrl;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmMaterialMapper materialMapper;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Override
    public ResponseResult findAll(WmNewsPageReqDto dto) {
        if (dto == null) return paramError;
        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
        if (dto.getStatus() != null) wrapper.eq(WmNews::getStatus, dto.getStatus());
        if (StringUtils.isNotBlank(dto.getKeyword())) wrapper.like(WmNews::getTitle, dto.getKeyword());
        if (dto.getChannelId() != null) wrapper.eq(WmNews::getChannelId, dto.getChannelId());
       /* if (dto.getBeginPubDate()!=null&&dto.getEndPubDate()!=null){
            wrapper.between(WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());
        }*/
        Integer userId = ThreadLocalUtils.getUser();
        if (userId == null) return needLogin;
        wrapper.eq(WmNews::getUserId, userId);
        if (dto.getMaxTime() == null) dto.setMaxTime(new Date());
        wrapper.lt(WmNews::getPublishTime, dto.getMaxTime());
        wrapper.orderByDesc(WmNews::getCreatedTime);
        ResponseResult pageResult = getPageResult(dto, wrapper);
        pageResult.setHost(baseUrl);
        return pageResult;
    }

    private void resetCovers(List<String> covers, WmNews wmNews) {
        //方法内部没有并发问题 就不会有线程安全问题
        StringBuffer buffer = new StringBuffer();
        //遍历字符串 如果http开头的话 使用baseUrl替掉 没有就会执行s
        covers.forEach(s -> buffer.append(s.contains("http") ? s.replace(baseUrl, "") : s).append(","));
        //转成字符串 最后还有一个逗号，使用substring截取字符串 长度减一
        String urls = buffer.toString().substring(0, buffer.toString().length() - 1);
        //保存
        wmNews.setImages(urls);
    }

    /**
     * 自媒体文章发布
     *
     * @param dto      前端传过来要保存的新闻对象
     * @param isSubmit 是否为提交 1 为提交 0为草稿
     * @return
     */

    @Override                                     //isSubmit 0草稿 1提交
    public ResponseResult saveNews(WmNewsDto dto, Short isSubmit) {
        //判断图文内容和实体信息是否为空
        if (dto == null || StringUtils.isBlank(dto.getContent())) return paramError;
        WmNews wmNews = new WmNews();
        try {
            //保存新闻有更新的情况 拷贝对象
            BeanUtils.copyProperties(wmNews, dto);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //如果是-1赋值为空
        if (WemediaContans.WM_NEWS_TYPE_AUTO == dto.getType()) wmNews.setType(null);
        //图片转换成字符串格式不规范
        if (dto.getImages().isEmpty() && dto.getType() != WemediaContans.WM_NEWS_TYPE_AUTO) {
            resetCovers(dto.getImages(), wmNews);
        }
        wmNews.setUserId(ThreadLocalUtils.getUser());
        if (wmNews.getCreatedTime() == null) wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setStatus(isSubmit);
        wmNews.setPublishTime(new Date());
        wmNews.setEnable((short) 1);
        boolean flag = false;
        if (wmNews.getId() == null) {
            flag = save(wmNews);
        } else {
            //如果是修改，则先删除素材与文章的关系
            LambdaQueryWrapper<WmNewsMaterial> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(WmNewsMaterial::getNewsId, wmNews.getId());
            wmNewsMaterialMapper.delete(queryWrapper);
            flag = updateById(wmNews);
        }
        //发送消息
        if (flag) {
            kafkaTemplate.send(WM_NEWS_AUTO_SCAN_TOPIC, JSON.toJSONString(wmNews.getId()));
        }
        //处理关系表中新闻和素材的关系(关系表中插入数据)
        List<String> urlList = getUrlList(wmNews); //内容中图片集合
        List<String> covers = dto.getImages();     //前端传过来的封面集合
        //保存文章内容中的图片和新闻的关系数据
        if (isSubmit == WmNews.Status.SUBMIT.getCode()) {
            saveCP(urlList, wmNews, WemediaContans.WM_CONTENT_REFERENCE);
            //当前端并没有对封面是几图进行指定时，默认是自动，而自动并不会使用news中的images中的图片路径
            //而是使用内容中的图片，当然是几图模式由内容中图片的数量决定
            if (dto.getType().equals(WemediaContans.WM_NEWS_TYPE_AUTO)) {
                if (urlList.size() == 1 || urlList.size() == 2) { //单图模式
                    wmNews.setType(WemediaContans.WM_NEWS_SINGLE_IMAGE);
                    covers = Arrays.asList(urlList.get(0));
                } else if (urlList.size() > 2) { //多图模式
                    wmNews.setType(WemediaContans.WM_NEWS_MANY_IMAGE);
                    covers = urlList.stream().limit(3).collect(Collectors.toList());
                } else {
                    wmNews.setType(WemediaContans.WM_NEWS_NONE_IMAGE);
                    if (covers != null) covers.clear();
                }
                //重新赋值 逗号拼接
                if (covers != null || covers.size() != 0) resetCovers(covers, wmNews);
                updateById(wmNews);
                saveCP(covers, wmNews, WemediaContans.WM_COVER_REFERENCE);
            }
        }

        return okResult;
    }


    private void saveCP(List<String> urlList, WmNews wmNews, int type) {
        if (urlList.size() != 0) {
            List<WmMaterial> materialList = materialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, urlList));
            List<Integer> idList = materialList.stream().map(m -> m.getId()).collect(Collectors.toList());
            wmNewsMaterialMapper.saveRelationsByContent(idList, wmNews.getId(), type);
        }
    }

    private List<String> getUrlList(WmNews wmNews) {
        String content = wmNews.getContent();
        //写法1
         /*JSONArray array = JSON.parseArray(content);
        List<String> list = new ArrayList<>();
        //写法1
        array.forEach(o -> {
            JSONObject object = JSON.parseObject(o.toString());
            if (object.get("type").equals(WemediaContans.WM_NEWS_TYPE_IMAGE)) {
                String value = (String) object.get("value");
                value = value.replace(baseUrl, "");
                list.add(value);
            }
        });*/
        //写法2
        /*List<Map> maps = JSON.parseArray(content, Map.class);
        maps.forEach(m -> {
            if (m.get("type").equals(WemediaContans.WM_NEWS_TYPE_IMAGE)) {
                String url = (String) m.get("value");
                url = url.replace(baseUrl, "");
                list.add(url);
            }
        });*/
        //写法3
        //把内容转成ListMap集合 遍历时取出每一个map 每个map将type图片过滤出来 交给map操作符转换 通过value取出字符串 把baseUrl用空串替换 在新集合里面加进去
        return JSON.parseArray(content, Map.class).stream().filter(map -> map.get("type").equals(WemediaContans.WM_NEWS_TYPE_IMAGE)).map(map -> ((String) map.get("value")).replace(baseUrl, "")).collect(Collectors.toList());
    }

    @Override
    //自媒体文章-删除
    public ResponseResult delNews(Integer id) {
        if (id == null) return paramError;
        WmNews wm = getById(id);
        if (wm == null) return noData;
        if (wm.getStatus() == WmNews.Status.PUBLISHED.getCode())
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "该新闻已发布");
        if (wm.getEnable() == 1) return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "上架新闻不能删除");
        removeById(id);
        wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId, id));
        return okResult;
    }

    @Override
    //自媒体文章-上架、下架
    public ResponseResult downOrUp(WmNewsDto dto) {
        if (dto == null || dto.getId() == null || dto.getEnable() == null) return paramError;
        if (dto.getEnable() != 0 && dto.getEnable() != 1) return paramError;
        WmNews news = getById(dto.getId());
        if (news == null) return noData;
        if (news.getStatus() != WmNews.Status.PUBLISHED.getCode())
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "文章未发布，不能上下架");
        //更新Enable的值
        update(Wrappers.<WmNews>lambdaUpdate().eq(WmNews::getId, dto.getId()).set(WmNews::getEnable, dto.getEnable()));
        if (news.getArticleId() != null) {
            Map<String, Object> params = new HashMap<>();
            params.put("enable", dto.getEnable());
            params.put("articleId", news.getArticleId());
            kafkaTemplate.send(WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(params));
        }
        return okResult;
    }

    @Override
    public WmNews findById(Integer id) {
        if (id == null) return null;
        return getById(id);
    }

    @Override
    public ResponseResult updateWmNews(WmNews wmNews) {
        if (wmNews == null) return paramError;
        updateById(wmNews);
        return okResult;

    }

    @Override
    public List<Integer> findRelease() {
        //查询状态为8
        List<WmNews> list = list(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getStatus, WmNews.Status.SUCCESS.getCode()).lt(WmNews::getPublishTime, new Date()));
        List<Integer> collect = list.stream().map(WmNews::getId).collect(Collectors.toList());
        return collect;
    }

    @Override
    public ResponseResult findList(NewsAuthDto dto) {
        if (dto == null) return paramError;
        dto.setPage((dto.getPage() - 1) * dto.getSize());
        dto.setTitle("%" + dto.getTitle() + "%");
        List<WmNewsVo> list = baseMapper.findListAndPage(dto);
        ResponseResult result = new PageResponseResult(dto.getPage(), dto.getSize(), baseMapper.findListCount(dto));
        result.setData(list);
        return result;
    }

    @Override
    public WmNewsVo findWmNewsVo(Integer id) {
        if (id == null) return null;
        WmNews news = getOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, id));
        WmUser wmUser = wmUserMapper.selectById(news.getUserId());
        WmNewsVo wmNewsVo = new WmNewsVo();
        try {
            BeanUtils.copyProperties(wmNewsVo, news);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        wmNewsVo.setAuthorName(wmUser.getName());
        return wmNewsVo;
    }

}
